<!--
 * @description  : 实地核查方位图-添加位置-标距组件
 * @create       : 2024-7-30
-->

<template>
  <view class="content">
    <view :style="{ width: getContainerWidth(), height: getContainerHeight() }" id="container"></view>
    <view class="m-market">
      <view class="handler" v-if="curGaugeType === 'manual'">
        <view class="wrap" @click="handlePlotPoint">
          <u-image width="20px" :src="`/static/certificate/plot_icon${isPlotPointMode ? '_active' : ''}.svg`" mode="widthFix"></u-image>
          <view class="label" :style="{ color: isPlotPointMode ? '#f78e00' : '' }">描点</view>
        </view>
        <view class="wrap" @click="handleGauge">
          <u-image width="20px" src="/static/certificate/gauge_icon.png" mode="widthFix"></u-image>
          <view class="label">标距</view>
        </view>
      </view>
      <view class="entity-list">
        <view class="entity" v-for="(item, index) in entityList" :key="index">
          <view class="title bold">
            <u-image class="cur-image min-width" width="16px" src="/static/market/new-location.png" mode="widthFix"></u-image>
            <view class="name">{{ curPositionName }}</view>
          </view>
          <view class="title bold width" :style="{ marginLeft: item.entityType === 'school' ? '-16rpx' : '-6rpx' }">
            <u-image
              :style="getTarImgstyle(item.entityType)"
              :width="item.entityType === 'school' ? '30px' : '21px'"
              :src="`/static/certificate/${item.entityType}_icon.svg`"
              mode="widthFix"
            ></u-image>
            <view class="name">{{ item.name }}</view>
          </view>
          <view class="line"></view>
          <view class="title">
            <view class="label">位置：</view>
            <view class="value">{{ item.address }}</view>
          </view>
          <view class="title">
            规划距离<view :class="['distance', 'bold']">{{ item.walkDistance }}</view
            >米
          </view>
          <view class="title">
            实际测量距离<view :class="['distance', 'bold', curGaugeType === 'manual' ? 'border' : '']" @click="handleDistanceEdit(item.id)">{{ item.manualDistance }}</view
            >米
            <view class="clearLine" v-if="curGaugeType === 'manual'" @click="clearLine(item.id)">清空线路</view>
          </view>
        </view>
      </view>
    </view>
    <u-modal title="实际测量距离(m)" ref="uModal" v-model="distanceModalShow" show-cancel-button async-close @confirm="distanceModalConfirm">
      <view class="slot-content">
        <u-input type="number" placeholder="" v-model="distanceModalInfo.distance" :clearable="false"></u-input>
      </view>
    </u-modal>
  </view>
</template>

<script>
import { AMapMixin } from "@/common/AMapMixin.js";

export default {
  mixins: [AMapMixin],
  props: {
    location: {
      type: Array,
      default: () => {
        return [];
      }
    },
    entityList: {
      type: Array,
      default: () => {
        return [];
      }
    },
    curGaugeType: {
      type: String,
      default: "walk"
    }
  },
  data() {
    return {
      curCords: null,
      // 当前地图上marker实例集合
      curMarkerMap: {},
      // 步行线路实例集合
      allWalkLineList: [],
      // 人工线路实例集合
      allManualLineList: [],
      // 当前地图上线路实例
      curMapLineList: [],
      // 是否为描点模式
      isPlotPointMode: false,
      // 当前被清除的线路id
      curClearedId: "",
      // 当前描点的marker集合
      curPlotPointMarkers: [],
      // 距离修改模态框
      distanceModalShow: false,
      distanceModalInfo: {}
    };
  },
  computed: {
    getTarImgstyle() {
      return type => {
        const flag = type === "school";
        return {
          marginRight: flag ? "10rpx" : "18rpx",
          marginTop: flag ? "-12rpx" : "",
          minWidth: flag ? "30px" : "21px"
        };
      };
    },
    // 当前位置名称
    curPositionName() {
      return this.$storage.get("curConfirmInfo").curPositionName;
    },
    // 底部数据栏高度
    bottomHeight() {
      const len = this.entityList.length;
      return len < 2 ? len * 145 + 46 : 340;
    }
  },
  created() {
    this.curCords = new AMap.LngLat(this.location[0], this.location[1]);
  },
  methods: {
    initAmap() {
      this.setMapInstance();
    },
    getContainerHeight() {
      let p = this.$u.sys().windowHeight - 44 - this.bottomHeight - this.$u.sys().statusBarHeight + "px";
      // #ifdef H5-DINGDING || H5-WECHAT
      p = this.$u.sys().windowHeight - this.bottomHeight - this.$u.sys().statusBarHeight + "px";
      // #endif
      return p;
    },
    getContainerWidth() {
      return this.$u.sys().windowWidth + "px";
    },
    setMapInstance() {
      if (!this.hasInited) return;
      this.amap = new AMap.Map("container", {
        center: this.curCords,
        showControlButton: true,
        zoom: 18
      });
      const _this = this;
      this.loadPlugin("AMap.ControlBar", function() {
        const controlBar = new AMap.ControlBar({
          position: {
            top: "56px",
            right: "10px"
          }
        });
        _this.amap.addControl(controlBar);
      });
      this.drawDefaultInstance();
      this.drawEntityInstance();
      this.drawLineInstance();
    },
    // 绘制地图上的默认实例 当前位置 & 区域
    drawDefaultInstance() {
      const curLocation = new AMap.Marker({
        title: "当前位置",
        icon: new AMap.Icon({
          size: new AMap.Size(20, 30),
          imageSize: new AMap.Size(20, 30),
          image: "static/market/new-location.png" // 大图地址
        }),
        position: this.curCords
      });
      curLocation.setMap(this.amap);
    },
    // 绘制零售户 | 学校
    drawEntityInstance() {
      // 绘制前先清除已绘制实例
      this.clearMarker();
      if (!this.entityList.length) {
        return;
      }
      this.entityList.forEach(item => {
        this.drawMarker(item);
      });
    },
    // 绘制marker
    drawMarker(entity) {
      const { name, id, entityType, longitude, latitude, distance } = entity;
      const sizes = entityType === "school" ? [40, 50] : [30, 40];
      const option = {
        title: name,
        icon: new AMap.Icon({
          image: `static/certificate/${entityType}_icon.svg`,
          size: new AMap.Size(sizes[0], sizes[1]),
          imageSize: new AMap.Size(sizes[0], sizes[1])
        }),
        position: [longitude, latitude],
        extData: { id, entityType }
      };
      const marker = new AMap.Marker(option);
      marker.setMap(this.amap);
      this.curMarkerMap[id] = marker;
    },
    // 传marker实例则单清，否则全清
    clearMarker(instance) {
      if (instance) {
        instance.setMap(null);
        const idx = this.curPlotPointMarkers.findIndex(item => item.getExtData().id === instance.getExtData().id);
        this.curPlotPointMarkers.splice(idx, 1);
      } else {
        Object.keys(this.curMarkerMap).forEach(key => {
          this.curMarkerMap[key].setMap(null);
        });
        this.curMarkerMap = {};
      }
    },
    // 绘制线路
    async drawLineInstance() {
      // 绘制前先清除已绘制线路
      this.clearPolyline();
      if (!this.entityList.length) {
        return;
      }
      for (let i = 0; i < this.entityList.length; i++) {
        const item = this.entityList[i];
        const route = await this.getRoutsData({
          destination: `${item.longitude},${item.latitude}`,
          isindoor: 1,
          key: "", // 很重要，不能删，占位置
          origin: `${this.location[0]},${this.location[1]}`,
          output: "JSON"
        });
        item.walkDistance = route.distance;
        item.manualDistance = route.distance;
        // marker label显示距离
        this.curMarkerMap[item.id].setLabel({
          direction: "right",
          content: `<view style="font-size: 14rpx; font-weight: bold">${item.name}<br /><view style="color: #f78e00">${item.manualDistance}米</view> </view>`
        });
        const paths = this.parseRouteToPath(route);
        // 将起点与终点加入线路中
        paths.unshift([+this.location[0], +this.location[1]]);
        paths.push([+item.longitude, +item.latitude]);
        this.drawPolyline(paths, item);
      }
      // 根据步行导航距离排序
      this.entityList = this.entityList.sort((a, b) => a.walkDistance - b.walkDistance);
      // 距离最近路径差异化
      this.handleNearestEntity();
      // 自适应展示所有线路
      // this.amap.setFitView(this.curMapLineList);
    },
    // 绘制线
    drawPolyline(paths, entity, isManual) {
      const option = {
        path: paths,
        isOutline: true,
        outlineColor: "#ffeeee",
        borderWeight: 2,
        strokeWeight: 5,
        strokeColor: "#0091ff",
        strokeOpacity: 0.9,
        lineJoin: "round",
        zIndex: 10,
        extData: { id: entity.id }
      };
      const polyLine = new AMap.Polyline(option);
      polyLine.setMap(this.amap);
      if (!isManual) {
        this.curMapLineList.push(polyLine);
        this.allWalkLineList.push(polyLine);
      }
      this.allManualLineList.push(polyLine);
    },
    // 解析WalkRoute对象，构造成AMap.Polyline的path参数需要的格式
    parseRouteToPath(route) {
      let paths = [];
      for (let i = 0, l = route.steps.length; i < l; i++) {
        let step = route.steps[i];
        let polyline = step.polyline.split(";");
        for (let j = 0, n = polyline.length; j < n; j++) {
          let routeItem = polyline[j].split(",");
          routeItem = [Number(routeItem[0]), Number(routeItem[1])];
          paths.push(routeItem);
        }
      }
      return paths;
    },
    handleNearestEntity() {
      const id = this.entityList[0].id;
      this.curMapLineList.forEach(line => {
        if (line.getExtData().id === id) {
          line.setOptions({
            strokeWeight: 7,
            strokeColor: "#FF6A71",
            zIndex: 11
          });
        }
      });
    },
    // 传polyLine实例则单清，否则全清
    clearPolyline(instance) {
      if (instance) {
        this.amap.remove(instance);
        const idx = this.allManualLineList.findIndex(item => item.getExtData().id === instance.getExtData().id);
        this.allManualLineList.splice(idx, 1);
      } else {
        this.amap.remove(this.curMapLineList);
        this.curMapLineList = [];
      }
    },
    // 清空线路
    clearLine(id) {
      // 限制连续点击清空线路
      if (this.allManualLineList.length !== this.entityList.length) {
        uni.showToast({
          title: "请先完成已清空线路的描点并标距",
          icon: "none"
        });
        return;
      }
      const polyline = this.findPolylineById(id);
      polyline && this.clearPolyline(polyline);
      let name = "";
      // 清空距离显示值
      this.entityList.forEach(item => {
        if (item.id === id) {
          item.manualDistance = 0;
          name = item.name;
          this.$forceUpdate();
        }
      });
      // 刷新label显示距离
      this.curMarkerMap[id].setLabel({
        content: `<view style="font-size: 14rpx; font-weight: bold">${name}<br /><view style="color: #f78e00">0米</view> </view>`
      });
      this.curClearedId = id;
    },
    // 根据id查找polyline实例
    findPolylineById(id) {
      let polyline = null;
      for (let item of this.allManualLineList) {
        if (item.getExtData().id === id) {
          polyline = item;
          break;
        }
      }
      return polyline;
    },
    // 切换标距类型回调
    gaugeChangeCallback() {
      // 指北针位置
      const ele = document.querySelector(".amap-controlbar");
      ele.style.top = this.curGaugeType === "walk" ? "56px" : "102px";
      // 重绘前清除已绘制线路
      this.clearPolyline();
      const list = this.curGaugeType === "walk" ? this.allWalkLineList : this.allManualLineList;
      this.curMapLineList = list;
      this.amap.add(this.curMapLineList);
      if (!this.curPlotPointMarkers.length) {
        return;
      }
      // 步行导航标距 不显示已描点
      this.curPlotPointMarkers.forEach(marker => {
        this.curGaugeType === "walk" ? marker.hide() : marker.show();
      });
    },
    // 描点
    handlePlotPoint() {
      if (!this.curClearedId) {
        uni.showToast({
          title: "请先清空需要描点的线路",
          icon: "none"
        });
        return;
      }
      this.isPlotPointMode = true;
      this.amap.on("click", this.plotPointCallback);
    },
    // 地图打点事件回调
    plotPointCallback(event) {
      const option = {
        icon: new AMap.Icon({
          image: "static/certificate/position_picker.png",
          imageSize: [30, 40]
        }),
        label: {
          content: `途经点${this.curPlotPointMarkers.length + 1}`,
          offset: new AMap.Pixel(22, 1)
        },
        position: event.lnglat,
        extData: {
          id: `${event.lnglat.getLng()}-${event.lnglat.getLat()}`
        }
      };
      const marker = new AMap.Marker(option);
      marker.on("click", e => {
        // 点击已绘制轨迹点删除
        const _this = this;
        const name = e.target.getLabel().content;
        uni.showModal({
          title: "提示",
          content: `确定要删除 ${name} 吗?`,
          success: function(res) {
            if (res.confirm) {
              _this.clearMarker(e.target);
            }
          }
        });
      });
      marker.setMap(this.amap);
      this.curPlotPointMarkers.push(marker);
    },
    // 标距
    handleGauge() {
      if (!this.curPlotPointMarkers.length) {
        uni.showToast({
          title: "请先描点，再进行标距",
          icon: "none"
        });
        return;
      }
      this.amap.off("click", this.plotPointCallback);
      const paths = this.curPlotPointMarkers.map(marker => {
        const position = marker.getPosition();
        return [position.getLng(), position.getLat()];
      });
      const info = this.entityList.filter(item => item.id === this.curClearedId)[0];
      // 连接起点 & 终点
      paths.unshift(this.location);
      paths.push([info.longitude, info.latitude]);
      this.drawPolyline(paths, { id: this.curClearedId, isNearest: info.isNearest }, true);
      // 测距
      let distance = 0;
      const len = paths.length;
      for (let i = 0; i < len - 1; i++) {
        const dis = paths[i].distance(paths[i + 1]);
        distance += Math.round(dis);
      }
      let name = "";
      this.entityList.forEach(item => {
        if (item.id === this.curClearedId) {
          item.manualDistance = distance;
          name = item.name;
        }
      });
      // 刷新label显示距离
      this.curMarkerMap[this.curClearedId].setLabel({
        content: `<view style="font-size: 14rpx; font-weight: bold">${name}<br /><view style="color: #f78e00">${distance}米</view> </view>`
      });
      // 后续处理
      this.isPlotPointMode = false;
      this.curClearedId = "";
      this.curPlotPointMarkers.forEach(marker => {
        marker.setMap(null);
      });
      this.curPlotPointMarkers = [];
    },
    // 编辑距离
    handleDistanceEdit(id) {
      if (this.curGaugeType === "walk") {
        return;
      }
      const { manualDistance, name } = this.entityList.find(item => item.id === id);
      this.distanceModalInfo = {
        id,
        name,
        distance: manualDistance
      };
      this.distanceModalShow = true;
    },
    // 编辑距离提交
    distanceModalConfirm() {
      // 校验
      this.$refs.uModal.clearLoading();
      const { id, distance, name } = this.distanceModalInfo;
      if (+distance > 200) {
        uni.showToast({
          title: "距离不能大于200米",
          icon: "none"
        });
        return;
      }
      if (distance.slice(distance.indexOf(".")).length > 3) {
        uni.showToast({
          title: "距离最多保留两位小数",
          icon: "none"
        });
        return;
      }
      this.distanceModalShow = false;
      this.entityList.forEach(item => {
        if (item.id === id) {
          item.manualDistance = distance;
        }
      });
      // 刷新label显示距离
      this.curMarkerMap[id].setLabel({
        content: `<view style="font-size: 14rpx; font-weight: bold">${name}<br /><view style="color: #f78e00">${distance}米</view> </view>`
      });
    }
  }
};
</script>

<style lang="scss" scoped>
#container {
  /* #ifdef H5 */
  width: 100%;
  height: calc(100% - 30rpx);
  /* #endif */
  /* #ifdef APP-PLUS */
  height: calc(100vh - 44 - var(--status-bar-height));
  margin-top: calc(44 + var(--status-bar-height));
  /* #endif */
}

.slot-content {
  padding: 0 40rpx;
  .u-input {
    border: 1px solid;
    margin: 40rpx 0;
  }
}

.m-market {
  position: fixed;
  bottom: 120rpx;
  left: 0;
  right: 0;
  z-index: 999;
  background-color: #ffffff;
  padding: 0 30rpx;
  .handler {
    position: absolute;
    top: -140rpx;
    left: 20rpx;
    padding: 14rpx;
    background-color: #ffffff;
    border-radius: 6rpx;
    .wrap {
      display: flex;
      .label {
        margin-left: 40rpx;
        font-size: 26rpx;
        font-weight: bold;
        color: #666666;
      }
    }
    .wrap:first-child {
      margin-bottom: 10rpx;
    }
  }

  .entity-list {
    max-height: 616rpx;
    overflow-y: auto;
    .entity {
      padding: 20rpx;
      border-bottom: 1px solid #cecece;
      position: relative;
      .bold {
        font-weight: bold;
      }
      .line {
        height: 22rpx;
        border-left: 1px solid #666;
        position: absolute;
        top: 76rpx;
        left: 36rpx;
      }
      .title {
        color: #333333;
        display: flex;
        font-size: 26rpx;
        margin: 10rpx 0;
        position: relative;
      }
      .title:last-child {
        margin-top: 16rpx;
      }
      .cur-image {
        margin-right: 20rpx;
      }
      .min-width {
        min-width: 16px;
      }
      .name {
        line-height: 50rpx;
        text-overflow: ellipsis;
        overflow: hidden;
        white-space: nowrap;
      }
      .label {
        color: #666666;
        font-weight: 100;
        white-space: nowrap;
      }
      .value {
        font-weight: 400;
      }
      .distance {
        color: #f78e00;
        margin: 0 20rpx;
      }
      .border {
        border: 1px solid #c7c7c7;
        padding: 0 10rpx;
      }
      .clearLine {
        color: #ffffff;
        background-color: #0070d2;
        padding: 10rpx 24rpx;
        border-radius: 8rpx;
        position: absolute;
        right: 0;
        bottom: -10rpx;
      }
    }
  }
}
</style>
